package com.yincheng.oes.business.util;

import com.yincheng.oes.business.model.export.dto.BaseExportWordDTO;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.*;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import javax.annotation.PostConstruct;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;

/**
 * @Author: yangsy
 * @Contact: 446948434@qq.com
 * @Date: 2021/9/5 10:45
 * @Version: 1.0
 * @Description:
 */
@Component
public class ExportWordUtils {
    /**
     * 日志
     */
    private static final Logger logger = LogManager.getLogger(ExportWordUtils.class);

    private Configuration configuration;

    private final static String separator = File.separator;
    private final static String suffix_docx = "docx";

    //    private final static String docxTemplateFile = "docTemplates.docx";
    private final static String xmlDocument = "document.xml";
    private final static String xmlDocumentXmlRels = "document.xml.rels";
    private final static String xmlContentTypes = "[Content_Types].xml";
    private final static String xmlHeader = "header1.xml";//可以用来修改页眉的一些信息

    private static File temFile = new File(Consists.parentPath);

    @PostConstruct
    public void init() {
        configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setDefaultEncoding("UTF-8");
        // configuration.setClassForTemplateLoading(this.getClass(), "/template/");
        try {
            configuration.setDirectoryForTemplateLoading(temFile);
        } catch (IOException e) {
            logger.error("configuration setDirectoryForTemplateLoading error", e);
        }
    }

    public File createWord(BaseExportWordDTO dto, String docxName, String templatePath) {
        try {
            return createDocx(dto, docxName, templatePath);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private File createDocx(BaseExportWordDTO dto, String docxName, String templatePath) throws Exception {

        String outputFileName = dto.getTitle() + "." + suffix_docx;

        //获取 document.xml.rels 输入流
//        ByteArrayInputStream documentXmlRelsInput = this.getFreemarkerContentInputStream(dto, "/" + templatePath + "/" + xmlDocumentXmlRels);
        //获取 header1.xml 输入流
//        ByteArrayInputStream headerInput = this.getFreemarkerContentInputStream(dto, "/" + templatePath + "/" + xmlHeader);
        //获取 [Content_Types].xml 输入流
//        ByteArrayInputStream contentTypesInput = this.getFreemarkerContentInputStream(dto, "/" + templatePath + "/" + xmlContentTypes);
        //获取 document.xml 输入流
        ByteArrayInputStream documentInput = this.getFreemarkerContentInputStream(dto, "/" + templatePath + "/" + xmlDocument);

        File docxTmpFile = new File(com.yincheng.oes.business.consist.Consists.BASE_FILE_PATH + separator + "template" + separator + docxName);
        if (!docxTmpFile.exists()) {
            docxTmpFile.createNewFile();
        }

        ZipFile zipFile = new ZipFile(docxTmpFile);
        Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();

        File word = FileUtils.getFile(ExportFileUtils.getTmpBaseFile(), outputFileName);
        ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(word));

        //------------------覆盖文档------------------
        int len = -1;
        byte[] buffer = new byte[1024];
        while (zipEntrys.hasMoreElements()) {
            ZipEntry next = zipEntrys.nextElement();
            InputStream is = zipFile.getInputStream(next);
//            if (next.toString().indexOf("media") < 0) {
            // 把输入流的文件传到输出流中 如果是word/document.xml由我们输入
            zipout.putNextEntry(new ZipEntry(next.getName()));
            //写入图片配置类型
//                if (next.getName().equals("[Content_Types].xml")) {
//                    this.writeOutputStream(contentTypesInput, zipout, buffer, len);
//                } else if (next.getName().indexOf("document.xml.rels") > 0) {
//                    //写入填充数据后的主数据配置信息
//                    this.writeOutputStream(documentXmlRelsInput, zipout, buffer, len);
//                } else if ("word/document.xml".equals(next.getName())) {
//                    //写入填充数据后的主数据信息
//                    this.writeOutputStream(documentInput, zipout, buffer, len);
//                } else if ("word/header1.xml".equals(next.getName())) {
//                    //写入填充数据后的页眉信息
//                    this.writeOutputStream(headerInput, zipout, buffer, len);
//                } else {
//                    while ((len = is.read(buffer)) != -1) {
//                        zipout.write(buffer, 0, len);
//                    }
//                    is.close();
//                }

            if ("word/document.xml".equals(next.getName())) {
                //写入填充数据后的主数据信息
                this.writeOutputStream(documentInput, zipout, buffer, len);
            } else {
                while ((len = is.read(buffer)) != -1) {
                    zipout.write(buffer, 0, len);
                }
                is.close();
            }

//            }
        }
        zipout.close();
        zipFile.close();
        return word;
    }

    public ByteArrayInputStream getFreemarkerContentInputStream(Object dataMap, String templateName) {
        //获取模板
        Template template;
        try {
            template = configuration.getTemplate(templateName);
        } catch (IOException e) {
            logger.error("configuration getTemplate error", e);
            return null;
        }
        StringWriter swriter = new StringWriter();
        //生成文件
        try {
            template.process(dataMap, swriter);
        } catch (TemplateException | IOException e) {
            logger.error("template process error", e);
        }
        return new ByteArrayInputStream(swriter.toString().getBytes());
    }

    private void writeOutputStream(ByteArrayInputStream input, ZipOutputStream zipout, byte[] buffer, int len) throws
            Exception {
        if (input != null) {
            while ((len = input.read(buffer)) != -1) {
                zipout.write(buffer, 0, len);
            }
            input.close();
        }
    }

}
